﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SpriteMaker
{
    public partial class FrameWorkingPanel : Control
    {
        //private Image texture;
        private int xCoord, yCoord;
        private float zoom = 1.0f;
        private int lastMouseX, lastMouseY;
        private float moduleOriginalX, moduleOriginalY;
        private Frame activeFrame;
        private FrameModule activeFrameModule;
        public formMain formInstance;
        private int delta = 2;
        private enum MouseModuleState
        {
            None,
            Drag,
            ResizeLeft,
            ResizeRight,
            ResizeTop,
            ResizeBottom,
            ResizeLeftTop,
            ResizeLeftBottom,
            ResizeRightTop,
            ResizeRightBottom,
        }
        private MouseModuleState mouseState = MouseModuleState.None;
        public FrameWorkingPanel()
        {
            InitializeComponent();
            this.DoubleBuffered = true;
            xCoord = this.ClientSize.Width / 2;
            yCoord = this.ClientSize.Height / 2;
            this.MouseWheel += FrameWorkingPanel_MouseWheel;
        }

        void FrameWorkingPanel_MouseWheel(object sender, MouseEventArgs e)
        {
            int numberOfTextLinesToMove = e.Delta / 120;
            zoom += numberOfTextLinesToMove * 0.5f;
            if (zoom < 0.5f)
            {
                zoom = 0.5f;
            }
            this.Refresh();
        }
        public Frame GetActiveFrame()
        {
            return activeFrame;
        }
        public FrameModule GetActiveFrameModule()
        {
            return activeFrameModule;
        }
        /*
        public void SetImage(Image im)
        {
            texture = im;
            this.Refresh();
        }
        */
        public void SetActiveFrame(Frame frame)
        {
            activeFrame = frame;
            this.Refresh();
        }
        public void SetActiveFrameModule(FrameModule fm)
        {
            activeFrameModule = fm;
        }
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            pe.Graphics.Clear(Color.Gray);
            System.Drawing.Drawing2D.GraphicsContainer container = pe.Graphics.BeginContainer();
            pe.Graphics.TranslateTransform(xCoord, yCoord);
            pe.Graphics.ScaleTransform(zoom, zoom);
            if (activeFrame != null && formInstance.GetImage() != null)
            {
                foreach (FrameModule frameModule in activeFrame.frameModuleList)
                {
                    pe.Graphics.DrawImage(formInstance.GetImage()
                    , new Rectangle(frameModule.x, -frameModule.y - frameModule.height, frameModule.width, frameModule.height)
                        , new Rectangle(frameModule.module.x, frameModule.module.y, frameModule.module.width, frameModule.module.height), GraphicsUnit.Pixel);
                }
            }
            Pen line = new Pen(Color.DarkRed);
            line.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            pe.Graphics.DrawLine(line, new Point(-Width/2, 0), new Point(Width/2, 0));
            pe.Graphics.DrawLine(line, new Point(0, -Height/2), new Point(0, Height/2));
            if (activeFrameModule != null)
            {
                Pen pen = new Pen(Color.FromArgb(150, 50, 255, 50));
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
                pe.Graphics.DrawRectangle(pen, activeFrameModule.x, -activeFrameModule.y - activeFrameModule.height, activeFrameModule.width, activeFrameModule.height);
            }
            pe.Graphics.EndContainer(container);
        }

        private void FrameWorkingPanel_Resize(object sender, EventArgs e)
        {
            xCoord = this.ClientSize.Width / 2;
            yCoord = this.ClientSize.Height / 2;
            this.Refresh();
        }

        private void FrameWorkingPanel_MouseDown(object sender, MouseEventArgs e)
        {
            int x = (int)((e.X - xCoord) / zoom);
            int y = (int)((e.Y - yCoord) / zoom);
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (activeFrameModule != null && Util.PointInRect(x, y, activeFrameModule.x, -activeFrameModule.y - activeFrameModule.height
                    , activeFrameModule.width, activeFrameModule.height))
                {
                    int yNew = -activeFrameModule.y - activeFrameModule.height;
                    if (x <= activeFrameModule.x + delta && y <= yNew + delta)
                    {
                        mouseState = MouseModuleState.ResizeLeftTop;
                        this.Cursor = Cursors.SizeNWSE;
                        moduleOriginalX = activeFrameModule.x;
                        moduleOriginalY = activeFrameModule.height;
                    }
                    else if (x <= activeFrameModule.x + delta && y >= yNew + activeFrameModule.height - delta)
                    {
                        mouseState = MouseModuleState.ResizeLeftBottom;
                        this.Cursor = Cursors.SizeNESW;
                        moduleOriginalX = activeFrameModule.x;
                        moduleOriginalY = activeFrameModule.y;
                    }
                    else if (x >= activeFrameModule.x + activeFrameModule.width - delta && y <= yNew + delta)
                    {
                        mouseState = MouseModuleState.ResizeRightTop;
                        this.Cursor = Cursors.SizeNESW;
                        moduleOriginalX = activeFrameModule.width;
                        moduleOriginalY = activeFrameModule.height;
                    }
                    else if (x >= activeFrameModule.x + activeFrameModule.width - delta && y >= yNew + activeFrameModule.height - delta)
                    {
                        mouseState = MouseModuleState.ResizeRightBottom;
                        this.Cursor = Cursors.SizeNWSE;
                        moduleOriginalX = activeFrameModule.width;
                        moduleOriginalY = activeFrameModule.y;
                    }
                    else if (x <= activeFrameModule.x + delta)
                    {
                        mouseState = MouseModuleState.ResizeLeft;
                        this.Cursor = Cursors.SizeWE;
                        moduleOriginalX = activeFrameModule.x;
                    }
                    else if (x >= activeFrameModule.x + activeFrameModule.width - delta)
                    {
                        mouseState = MouseModuleState.ResizeRight;
                        this.Cursor = Cursors.SizeWE;
                        moduleOriginalX = activeFrameModule.width;
                    }
                    else if (y <= yNew + delta)
                    {
                        mouseState = MouseModuleState.ResizeTop;
                        this.Cursor = Cursors.SizeNS;
                        moduleOriginalY = activeFrameModule.height;
                    }
                    else if (y >= yNew + activeFrameModule.height - delta)
                    {
                        mouseState = MouseModuleState.ResizeBottom;
                        this.Cursor = Cursors.SizeNS;
                        moduleOriginalY = activeFrameModule.y;
                    }
                    else
                    {
                        mouseState = MouseModuleState.Drag;
                        this.Cursor = Cursors.Hand;
                        moduleOriginalX = activeFrameModule.x;
                        moduleOriginalY = activeFrameModule.y;
                    }
                }
            }
            lastMouseX = e.X;
            lastMouseY = e.Y;
        }

        private void FrameWorkingPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (mouseState == MouseModuleState.Drag)
                {
                    moduleOriginalX += (e.X - lastMouseX) / zoom;
                    moduleOriginalY -= (e.Y - lastMouseY) / zoom;
                    activeFrameModule.x = (int)moduleOriginalX;
                    activeFrameModule.y = (int)moduleOriginalY;
                    this.Refresh();
                    formInstance.UpdateActiveFrameModule();
                }
                else if (mouseState == MouseModuleState.ResizeBottom)
                {
                    moduleOriginalY -= (e.Y - lastMouseY) / zoom;
                    int newHeight = Math.Max(1, (activeFrameModule.y + activeFrameModule.height) - (int)moduleOriginalY);
                    activeFrameModule.y -= newHeight - activeFrameModule.height;
                    activeFrameModule.height = newHeight;
                    this.Refresh();
                    formInstance.UpdateActiveFrameModule();
                }
                else if (mouseState == MouseModuleState.ResizeLeft)
                {
                    moduleOriginalX += (e.X - lastMouseX) / zoom;
                    int newWidth = Math.Max(1, (activeFrameModule.x + activeFrameModule.width) - (int)moduleOriginalX);
                    activeFrameModule.x -= newWidth - activeFrameModule.width;
                    activeFrameModule.width = newWidth;
                    this.Refresh();
                    formInstance.UpdateActiveFrameModule();
                }
                else if (mouseState == MouseModuleState.ResizeLeftBottom)
                {
                    moduleOriginalX += (e.X - lastMouseX) / zoom;
                    moduleOriginalY -= (e.Y - lastMouseY) / zoom;
                    int newHeight = Math.Max(1, (activeFrameModule.y + activeFrameModule.height) - (int)moduleOriginalY);
                    activeFrameModule.y -= newHeight - activeFrameModule.height;
                    activeFrameModule.height = newHeight;
                    int newWidth = Math.Max(1, (activeFrameModule.x + activeFrameModule.width) - (int)moduleOriginalX);
                    activeFrameModule.x -= newWidth - activeFrameModule.width;
                    activeFrameModule.width = newWidth;
                    this.Refresh();
                    formInstance.UpdateActiveFrameModule();
                }
                else if (mouseState == MouseModuleState.ResizeLeftTop)
                {
                    moduleOriginalX += (e.X - lastMouseX) / zoom;
                    moduleOriginalY -= (e.Y - lastMouseY) / zoom;
                    activeFrameModule.height = Math.Max((int)moduleOriginalY, 1);
                    int newWidth = Math.Max(1, (activeFrameModule.x + activeFrameModule.width) - (int)moduleOriginalX);
                    activeFrameModule.x -= newWidth - activeFrameModule.width;
                    activeFrameModule.width = newWidth;
                    this.Refresh();
                    formInstance.UpdateActiveFrameModule();
                }
                else if (mouseState == MouseModuleState.ResizeRight)
                {
                    moduleOriginalX += (e.X - lastMouseX) / zoom;
                    activeFrameModule.width = Math.Max((int)moduleOriginalX, 1);
                    this.Refresh();
                    formInstance.UpdateActiveFrameModule();
                }
                else if (mouseState == MouseModuleState.ResizeRightBottom)
                {
                    moduleOriginalX += (e.X - lastMouseX) / zoom;
                    moduleOriginalY -= (e.Y - lastMouseY) / zoom;
                    activeFrameModule.width = Math.Max((int)moduleOriginalX, 1);
                    int newHeight = Math.Max(1, (activeFrameModule.y + activeFrameModule.height) - (int)moduleOriginalY);
                    activeFrameModule.y -= newHeight - activeFrameModule.height;
                    activeFrameModule.height = newHeight;
                    this.Refresh();
                    formInstance.UpdateActiveFrameModule();
                }
                else if (mouseState == MouseModuleState.ResizeRightTop)
                {
                    moduleOriginalX += (e.X - lastMouseX) / zoom;
                    moduleOriginalY -= (e.Y - lastMouseY) / zoom;
                    activeFrameModule.width = Math.Max((int)moduleOriginalX, 1);
                    activeFrameModule.height = Math.Max((int)moduleOriginalY, 1);
                    this.Refresh();
                    formInstance.UpdateActiveFrameModule();
                }
                else if (mouseState == MouseModuleState.ResizeTop)
                {
                    moduleOriginalY -= (e.Y - lastMouseY) / zoom;
                    activeFrameModule.height = Math.Max((int)moduleOriginalY, 1);
                    this.Refresh();
                    formInstance.UpdateActiveFrameModule();
                }
                else
                {
                    xCoord += e.X - lastMouseX;
                    yCoord += e.Y - lastMouseY;
                    this.Refresh();
                }
            }
            else if (e.Button == System.Windows.Forms.MouseButtons.Middle)
            {
                xCoord += e.X - lastMouseX;
                yCoord += e.Y - lastMouseY;
                this.Refresh();
            }
            else if(e.Button == System.Windows.Forms.MouseButtons.None)
            {
                int x = (int)((e.X - xCoord) / zoom);
                int y = (int)((e.Y - yCoord) / zoom);

                if (activeFrameModule!= null && Util.PointInRect(x, y, activeFrameModule.x, -activeFrameModule.y - activeFrameModule.height
                        , activeFrameModule.width, activeFrameModule.height))
                {
                    int yNew = -activeFrameModule.y - activeFrameModule.height;

                    if (x <= activeFrameModule.x + delta && y <= yNew + delta)
                    {
                        this.Cursor = Cursors.SizeNWSE;
                    }
                    else if (x <= activeFrameModule.x + delta && y >= yNew + activeFrameModule.height - delta)
                    {
                        this.Cursor = Cursors.SizeNESW;
                    }
                    else if (x >= activeFrameModule.x + activeFrameModule.width - delta && y <= yNew + delta)
                    {
                        this.Cursor = Cursors.SizeNESW;
                    }
                    else if (x >= activeFrameModule.x + activeFrameModule.width - delta && y >= yNew + activeFrameModule.height - delta)
                    {
                        this.Cursor = Cursors.SizeNWSE;
                    }
                    else if (x <= activeFrameModule.x + delta)
                    {
                        this.Cursor = Cursors.SizeWE;
                    }
                    else if (x >= activeFrameModule.x + activeFrameModule.width - delta)
                    {
                        this.Cursor = Cursors.SizeWE;
                    }
                    else if (y <= yNew + delta)
                    {
                        this.Cursor = Cursors.SizeNS;
                    }
                    else if (y >= yNew + activeFrameModule.height - delta)
                    {
                        this.Cursor = Cursors.SizeNS;
                    }
                    else
                    {
                        this.Cursor = Cursors.Hand;
                    }
                }
                else if (this.Cursor != Cursors.Default)
                {
                    this.Cursor = Cursors.Default;
                }
            }
            lastMouseX = e.X;
            lastMouseY = e.Y;
        }

        private void FrameWorkingPanel_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (mouseState == MouseModuleState.Drag)
                {
                    activeFrameModule.x += e.X - lastMouseX;
                    activeFrameModule.y -= e.Y - lastMouseY;
                    formInstance.UpdateActiveFrameModule();
                    this.Refresh();
                }
                else
                {
                    xCoord += e.X - lastMouseX;
                    yCoord += e.Y - lastMouseY;
                    this.Refresh();
                }
                mouseState = MouseModuleState.None;
            }
            else if(e.Button == System.Windows.Forms.MouseButtons.Middle)
            {
                xCoord += e.X - lastMouseX;
                yCoord += e.Y - lastMouseY;
                this.Refresh();
            }
        }

        private void FrameWorkingPanel_MouseClick(object sender, MouseEventArgs e)
        {
            this.Focus();
        }
    }
}
